package keni.html.android.framework.metadata;

import java.io.IOException;
import java.util.Hashtable;
import java.util.Map;
import java.util.Stack;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import keni.html.android.framework.util.Constants;
import keni.html.formFlow.R;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
import android.util.Log;


public class MetadataParser {
	public Map<String, PageMetadata> parse(Context context) throws XmlPullParserException, IOException
	{
		Map<String, PageMetadata> metadatas = new Hashtable<String, PageMetadata>();
		Stack<Object> metadataElementStack=new Stack<Object>();
		Resources res = context.getResources();
		XmlResourceParser xmlParser = res.getXml(R.xml.form_metadata);
		int eventType = xmlParser.next();
		while (true) {
			String tagName=xmlParser.getName();
			if (eventType == XmlPullParser.START_TAG) {
				if(tagName.equalsIgnoreCase(Constants.MetadataTagName.PAGE))
				{
					metadataElementStack.push(parseMetadata(xmlParser,PageMetadata.class));
				}
				if(tagName.equalsIgnoreCase(Constants.MetadataTagName.FIELD))
				{
					metadataElementStack.push(parseMetadata(xmlParser,FieldMetadata.class));
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.PANEL)) {
					metadataElementStack.push(parseMetadata(xmlParser,PanelMetadata.class));
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.FIELDSET)) {
					metadataElementStack.push(parseMetadata(xmlParser,FieldSetMetadata.class));
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.CAROUSEL)) {
					metadataElementStack.push(parseMetadata(xmlParser,CarouselMetadata.class));
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.MODEL)) {
					metadataElementStack.push(parseMetadata(xmlParser,DataModel.class));
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.DATAFIELD)) {
					metadataElementStack.push(parseMetadata(xmlParser,DataFieldMetadata.class));
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.VALIDATION)) {
					metadataElementStack.push(parseMetadata(xmlParser,ValidationsMetadata.class));
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.ASSOCIATION)) {
					metadataElementStack.push(parseMetadata(xmlParser,AssociationMetadata.class));
				}
			    if (tagName.equalsIgnoreCase(Constants.MetadataTagName.TPL)||
					tagName.equalsIgnoreCase(Constants.MetadataTagName.HTML)) {
		
					eventType=xmlParser.nextToken();
					metadataElementStack.add(xmlParser.getText());
					continue;
				}
				
			}
			if (eventType == XmlPullParser.END_TAG) {
				if(tagName.equalsIgnoreCase(Constants.MetadataTagName.PAGE))
				{
					 PageMetadata pageMetadata=(PageMetadata)metadataElementStack.pop();
					 metadatas.put(pageMetadata.getElementId(), pageMetadata);
				}
				if(tagName.equalsIgnoreCase(Constants.MetadataTagName.FIELD))
				{
					FieldMetadata fieldMetadata= (FieldMetadata)metadataElementStack.pop();
					Object parent=metadataElementStack.peek();
					if(parent instanceof FieldContainer)
					{
						FieldContainer fieldContainer=(FieldContainer)parent;
						fieldContainer.setFields(fieldMetadata);
					}
					
				}
				if(tagName.equalsIgnoreCase(Constants.MetadataTagName.CAROUSEL))
				{
					CarouselMetadata carouselMetadata=(CarouselMetadata) metadataElementStack.pop();
					Object parent=metadataElementStack.peek();
					if(parent instanceof PageMetadata)
					{
						PageMetadata pageMetadata=(PageMetadata)parent;
						pageMetadata.carousels.add(carouselMetadata);
					}
					
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.PANEL)) {
					PanelMetadata panelMetadata= (PanelMetadata)metadataElementStack.pop();
					Object parent=metadataElementStack.peek();
					if(parent instanceof PageMetadata)
					{
						PageMetadata pageMetadata=(PageMetadata)parent;
						pageMetadata.panels.add(panelMetadata);
						
					}
					if(parent instanceof CarouselMetadata)
					{
						CarouselMetadata carouselMetadata=(CarouselMetadata)parent;
						carouselMetadata.panels.add(panelMetadata);
					}
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.FIELDSET)) {
					FieldSetMetadata fieldSetMetadata= (FieldSetMetadata)metadataElementStack.pop();
					Object parent=metadataElementStack.peek();
					if(parent instanceof PanelMetadata)
					{
						PanelMetadata panelMetadata=(PanelMetadata)parent;
						panelMetadata.fieldSets.add(fieldSetMetadata);
						
					}
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.HTML)) {
					setCDataAttribute(Constants.MetadataTagName.HTML,metadataElementStack);
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.TPL)) {
					setCDataAttribute(Constants.MetadataTagName.TPL,metadataElementStack);
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.MODEL)) {
					DataModel dataModel= (DataModel)metadataElementStack.pop();
					Object parent=metadataElementStack.peek();
					if(parent instanceof FieldContainer)
					{
						FieldContainer fieldContainer=(FieldContainer)parent;
						fieldContainer.dataModel=dataModel;
						
					}
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.DATAFIELD)) {
					DataFieldMetadata dataFieldMetadata= (DataFieldMetadata)metadataElementStack.pop();
					Object parent=metadataElementStack.peek();
					if(parent instanceof DataModel)
					{
						DataModel  dataModel=(DataModel)parent;
						dataModel.fields.add(dataFieldMetadata);
						
					}
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.VALIDATION)) {
					ValidationsMetadata validationsMetadata= (ValidationsMetadata)metadataElementStack.pop();
					Object parent=metadataElementStack.peek();
					if(parent instanceof DataModel)
					{
						DataModel  dataModel=(DataModel)parent;
						dataModel.validationsMetadatas.add(validationsMetadata);
						
					}
				}
				if (tagName.equalsIgnoreCase(Constants.MetadataTagName.ASSOCIATION)) {
					AssociationMetadata associationMetadata= (AssociationMetadata)metadataElementStack.pop();
					Object parent=metadataElementStack.peek();
					if(parent instanceof DataModel)
					{
						DataModel  dataModel=(DataModel)parent;
						dataModel.associationMetadatas.add(associationMetadata);
						
					}
				}
			}
			
			if (eventType == XmlPullParser.END_DOCUMENT) {
				break;
			}
			
			eventType = xmlParser.next();
	
		}
		
		return metadatas;
	}
	
	private void setCDataAttribute(String name,Stack<Object> metadataElementStack)
	{
		String text=(String)metadataElementStack.pop();
		Object parent=metadataElementStack.peek();
		if(parent  instanceof ElementBase)
		{
			ElementBase elementBase=(ElementBase) parent;
			elementBase.setPropertities(name, text);
			
		}
	}
	

	
	private  <T extends ElementBase> T parseMetadata(XmlResourceParser xmlParser,Class<T> type) {
		T metadata=null;
		try {
			 metadata= type.newInstance();
			
			int attributeCount= xmlParser.getAttributeCount();
			for (int i = 0; i <attributeCount; i++) {
				
				metadata.setPropertities(xmlParser.getAttributeName(i), xmlParser.getAttributeValue(i));
			}
			
		} catch (Exception e) {
			Log.e(Constants.LogTag.METADATAPARSER,e.getMessage());
		}
		return metadata;
	}
	
	


}
